﻿using System;
using System.Drawing;
using System.IO;
using System.Threading.Tasks;
using System.Windows.Forms;
using Ants.SimpleDistributionProblem.DTO;
using Controller;
using System.Diagnostics;

namespace Srpp
{
    /// <summary>
    /// Class representing main form.
    /// </summary>
    public partial class MainForm : Form
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="MainForm" /> class.
        /// </summary>
        public MainForm()
        {
            this.InitializeComponent();
        }

        /// <summary>
        /// Handles the Click event of the openToolStripMenuItem control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
        private void OpenToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            if (openFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                try
                {
                    MainController mainController = new MainController();
                    Data data = mainController.OpenFile(openFileDialog.FileName);

                    TabPage tabPage = new TabPage()
                    {
                        Text = Path.GetFileName(openFileDialog.FileName),
                        AutoScroll = true
                    };

                    tabPage.Controls.Add(new TextBox()
                    {
                        Name = "textBoxAlpha",
                        Location = new Point(150, 20),
                        Text = "16"
                    });

                    tabPage.Controls.Add(new TextBox()
                    {
                        Name = "textBoxBeta",
                        Location = new Point(150, 46),
                        Text = "16"
                    });

                    tabPage.Controls.Add(new TextBox()
                    {
                        Name = "textBoxCoefficientOfEvaporation",
                        Location = new Point(150, 72),
                        Text = "0,6"
                    });

                    tabPage.Controls.Add(new TextBox()
                    {
                        Name = "textBoxInitialPheromoneAmount",
                        Location = new Point(150, 98),
                        Text = "2"
                    });

                    tabPage.Controls.Add(new TextBox()
                    {
                        Name = "textBoxNumberOfAnts",
                        Location = new Point(150, 124),
                        Text = "100"
                    });

                    tabPage.Controls.Add(new TextBox()
                    {
                        Name = "textBoxNumberOfIterations",
                        Location = new Point(150, 150),
                        Text = "30"
                    });

                    tabPage.Controls.Add(new TextBox()
                    {
                        Name = "textBoxQParameter",
                        Location = new Point(150, 176),
                        Text = "2"
                    });

                    tabPage.Controls.Add(new TextBox()
                    {
                        Name = "textBoxNumberOfTasks",
                        Location = new Point(150, 202),
                        Text = "4"
                    });

                    tabPage.Controls.Add(new Label()
                    {
                        Text = "Alpha",
                        Location = new Point(110, 23),
                        Size = new Size(34, 13)
                    });

                    tabPage.Controls.Add(new Label()
                    {
                        Text = "Beta",
                        Location = new Point(115, 49),
                        Size = new Size(29, 13)
                    });

                    tabPage.Controls.Add(new Label()
                    {
                        Text = "Coefficient of evaporation",
                        Location = new Point(16, 75),
                        Size = new Size(128, 13)
                    });

                    tabPage.Controls.Add(new Label()
                    {
                        Text = "Initial pheromone amount",
                        Location = new Point(20, 101),
                        Size = new Size(150, 13)
                    });

                    tabPage.Controls.Add(new Label()
                    {
                        Text = "Number of ants",
                        Location = new Point(63, 127),
                        Size = new Size(79, 13)
                    });

                    tabPage.Controls.Add(new Label()
                    {
                        Text = "Number of iterations",
                        Location = new Point(43, 153),
                        Size = new Size(101, 13)
                    });

                    tabPage.Controls.Add(new Label()
                    {
                        Text = "Q parameter",
                        Location = new Point(77, 179),
                        Size = new Size(65, 13)
                    });

                    tabPage.Controls.Add(new Label()
                    {
                        Text = "Number of tasks",
                        Location = new Point(60, 205),
                        Size = new Size(84, 13)
                    });

                    Bitmap bitmap = new Bitmap(data.Size.Width + 20, data.Size.Height + 20);
                    Graphics graphics = Graphics.FromImage(bitmap);
                    graphics.DrawEllipse(new Pen(Color.Red, 4), new Rectangle(data.Cities[0], new Size(3, 3)));
                    for (int i = 1; i < data.Cities.Count; i++)
                    {
                        graphics.DrawEllipse(new Pen(Color.Black, 3), new Rectangle(data.Cities[i], new Size(3, 3)));
                    }

                    PictureBox pictureBox = new PictureBox()
                    {
                        Image = bitmap,
                        Location = new Point(270, 20),
                        Size = new Size(data.Size.Width + 20, data.Size.Height + 20)
                    };

                    tabPage.Controls.Add(pictureBox);

                    ProgressBar progressBar = new ProgressBar()
                    {
                        Visible = false,
                        Location = new Point(20, 257),
                        Size = new Size(228, 23)
                    };

                    tabPage.Controls.Add(progressBar);

                    mainController.FindSolutionProgressChanged += ((findSolutionSender, findSolutionArgs) =>
                        {
                            progressBar.BeginInvoke(((Action)(() =>
                                {
                                    progressBar.Value = findSolutionArgs.Progress;
                                })));
                        });

                    Label timeLeft = new Label()
                        {
                            Location = new Point(20, 283),
                            Size = new Size(228, 23)
                        };
                    tabPage.Controls.Add(timeLeft);

                    mainController.TimeLeftChanged += ((timeLeftChangedSender, timeLeftChangedArgs) =>
                        {
                            timeLeft.BeginInvoke((Action)(() =>
                                {
                                    timeLeft.Text = "Time left: ";
                                    if (timeLeftChangedArgs.TimeLeft.Days != 0)
                                    {
                                        timeLeft.Text += timeLeftChangedArgs.TimeLeft.Days.ToString() + "d ";
                                        timeLeft.Text += timeLeftChangedArgs.TimeLeft.Hours.ToString() + "h ";
                                        timeLeft.Text += timeLeftChangedArgs.TimeLeft.Minutes.ToString() + "m ";
                                        timeLeft.Text += timeLeftChangedArgs.TimeLeft.Seconds.ToString() + "s ";
                                    }
                                    else
                                    {
                                        if (timeLeftChangedArgs.TimeLeft.Hours != 0)
                                        {
                                            timeLeft.Text += timeLeftChangedArgs.TimeLeft.Hours.ToString() + "h ";
                                            timeLeft.Text += timeLeftChangedArgs.TimeLeft.Minutes.ToString() + "m ";
                                            timeLeft.Text += timeLeftChangedArgs.TimeLeft.Seconds.ToString() + "s ";
                                        }
                                        else
                                        {
                                            if (timeLeftChangedArgs.TimeLeft.Minutes != 0)
                                            {
                                                timeLeft.Text += timeLeftChangedArgs.TimeLeft.Minutes.ToString() + "m ";
                                                timeLeft.Text += timeLeftChangedArgs.TimeLeft.Seconds.ToString() + "s ";
                                            }
                                            else
                                            {
                                                timeLeft.Text += timeLeftChangedArgs.TimeLeft.Seconds.ToString() + "s ";
                                            }
                                        }
                                    }
                                }));
                        });

                    Button button = new Button()
                    {
                        Name = "buttonFindSolution",
                        Location = new Point(175, 228),
                        Text = "Find solution",
                    };

                    button.Click += (
                        (buttonSender, buttonArgs) =>
                        {
                            Task task = new Task((Action)(() =>
                                {
                                    progressBar.BeginInvoke((Action)(() => progressBar.Visible = true));
                                    bitmap = new Bitmap(data.Size.Width + 20, data.Size.Height + 20);
                                    graphics = Graphics.FromImage(bitmap);
                                    graphics.DrawEllipse(new Pen(Color.Red, 4), new Rectangle(data.Cities[0], new Size(3, 3)));
                                    for (int i = 1; i < data.Cities.Count; i++)
                                    {
                                        graphics.DrawEllipse(new Pen(Color.Black, 3), new Rectangle(data.Cities[i], new Size(3, 3)));
                                    }

                                    pictureBox.Image = bitmap;

                                    Stopwatch stopwatch = new Stopwatch();

                                    stopwatch.Start();
                                    Solution solution = mainController.FindSolution(
                                        data,
                                        new AntAlgorithmProperties()
                                        {
                                            Alpha = Convert.ToDouble(((TextBox)(tabPage.Controls["textBoxAlpha"])).Text),
                                            Beta = Convert.ToDouble(((TextBox)(tabPage.Controls["textBoxBeta"])).Text),
                                            CoefficientOfEvaporation = Convert.ToDouble(((TextBox)(tabPage.Controls["textBoxCoefficientOfEvaporation"])).Text),
                                            InitialPheromoneAmount = Convert.ToDouble(((TextBox)(tabPage.Controls["textBoxInitialPheromoneAmount"])).Text),
                                            NumberOfAnts = Convert.ToInt32(((TextBox)(tabPage.Controls["textBoxNumberOfAnts"])).Text),
                                            NumberOfIterations = Convert.ToInt32(((TextBox)(tabPage.Controls["textBoxNumberOfIterations"])).Text),
                                            QParameter = Convert.ToDouble(((TextBox)(tabPage.Controls["textBoxQParameter"])).Text),
                                            NumberOfThreads = Convert.ToInt32(((TextBox)(tabPage.Controls["textBoxNumberOfTasks"])).Text)
                                        });
                                    stopwatch.Stop();

                                    for (int i = 0; i < solution.Route.Count; i++)
                                    {
                                        graphics.DrawLine(new Pen(Color.Blue, 1.5f), solution.Route[i].PointA, solution.Route[i].PointB);
                                        graphics.DrawString((i + 1).ToString(), new Font(new FontFamily("Times New Roman"), 12), new SolidBrush(Color.Black), new PointF((solution.Route[i].PointA.X + solution.Route[i].PointB.X) / 2, (solution.Route[i].PointA.Y + solution.Route[i].PointB.Y) / 2));
                                    }

                                    pictureBox.Image = bitmap;

                                    mainController.SaveData(solution, data);

                                    MessageBox.Show("Route cost: " + solution.Cost + "\n"
                                        + "Elapsed time: " + stopwatch.Elapsed);
                                }));

                            task.Start();
                        });

                    tabPage.Controls.Add(button);
                    this.tabControl1.TabPages.Add(tabPage);
                }
                catch
                {
                    MessageBox.Show("Could not open file.");
                }
            }
        }
    }
}